package com.haixiaoke.saas.lock.service.impl;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.haixiaoke.saas.common.config.DevicesConfig;
import com.haixiaoke.saas.common.constant.DeviceLockConstants;
import com.haixiaoke.saas.common.constant.HttpStatus;
import com.haixiaoke.saas.common.core.domain.AjaxResult;
import com.haixiaoke.saas.common.core.page.TableDataInfo;
import com.haixiaoke.saas.common.exception.ServiceException;
import com.haixiaoke.saas.common.utils.DateUtils;
import com.haixiaoke.saas.lock.domain.*;
import com.haixiaoke.saas.lock.mapper.DeviceLockMapper;
import com.haixiaoke.saas.lock.service.*;
import com.haixiaoke.saas.lock.service.ILockFaceService;
import com.haixiaoke.saas.user.domain.User;
import com.haixiaoke.saas.user.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * 设备锁Service业务层处理
 *
 * @author panda
 * @date 2025-04-02
 */
@Slf4j
@Service
public class DeviceLockServiceImpl implements IDeviceLockService {
    @Autowired
    private DeviceLockMapper deviceLockMapper;
    @Autowired
    private LockDevicesService lockDevicesService;
    @Autowired
    private DevicesConfig devicesConfig;
    @Autowired
    private ILockFaceService lockFaceService;
    @Autowired
    private ILockPwdService lockPwdService;
    @Autowired
    private IUserService userService;
    @Autowired
    private ILockOperatingRecordService lockOperatingRecordService;
    @Autowired
    private IGroupService groupService;

    /**
     * 查询设备锁
     *
     * @param lockId 设备锁主键
     * @return 设备锁
     */
    @Override
    public DeviceLock selectDeviceLockById(Long lockId) {
        return deviceLockMapper.selectDeviceLockById(lockId);
    }

    @Override
    public DeviceLock selectDeviceLockByLockId(Long lockId) {
        return deviceLockMapper.selectDeviceLockByLockId(lockId);
    }

    /**
     * 查询设备锁列表
     *
     * @param deviceLock 设备锁
     * @return 设备锁
     */
    @Override
    public List<DeviceLock> selectDeviceLockList(DeviceLock deviceLock) {
        return deviceLockMapper.selectDeviceLockList(deviceLock);
    }

    @Override
    public List<DeviceLock> selectLockList(DeviceLock deviceLock) {
        return deviceLockMapper.selectLockList(deviceLock);
    }

    /**
     * 新增设备锁
     *
     * @param deviceLock 设备锁
     * @return 结果
     */
    @Override
    @Transactional
    public AjaxResult insertDeviceLock(DeviceLock deviceLock, User user) {
        if (ObjectUtil.isEmpty(deviceLock.getGroupId())) {
            Group group = groupService.selectDefaultGroupByUserId(user.getUserId());
            deviceLock.setGroupId(group.getGroupId());
        }
        AjaxResult ajaxResult = this.checkParam(deviceLock);
        if (ajaxResult != null) {
            return ajaxResult;
        }
        Date nowDate = DateUtils.getNowDate();
        deviceLock.setCreateTime(nowDate);
        deviceLock.setCreateBy(StrUtil.isBlank(user.getUserName()) ? user.getPhone() : user.getUserName());
        lockDevicesService.createSmartLock(deviceLock);
        int result = deviceLockMapper.insertDeviceLock(deviceLock);
        if (result > 0) {
            //新增默认主管理员
            LockFace lockFace = new LockFace();
            lockFace.setLockId(deviceLock.getLockId());
            lockFace.setGroupId(deviceLock.getGroupId());
            lockFace.setUserId(user.getUserId());
            lockFace.setUserName(StrUtil.isBlank(user.getUserName()) ? user.getPhone() : user.getUserName());
            lockFace.setUserPhone(user.getPhone());
            lockFace.setAuthRoleType(DeviceLockConstants.AUTH_ROLE_TYPE_MAIN_ADMIN);
            lockFace.setCreateTime(nowDate);
            lockFace.setCreateBy(StrUtil.isBlank(user.getUserName()) ? user.getPhone() : user.getUserName());
            lockFaceService.insertLockFace(lockFace);

            if (StrUtil.isBlank(deviceLock.getLockName())) {
                deviceLock.setLockName("智能锁" + deviceLock.getLockId());
                deviceLockMapper.updateDeviceLock(deviceLock);
            }
        }
        return result > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    /**
     * 修改设备锁
     *
     * @param deviceLock 设备锁
     * @return 结果
     */
    @Override
    public AjaxResult updateDeviceLock(DeviceLock deviceLock) {
        if (deviceLock.getLockId() == null) {
            return AjaxResult.error("设备锁修改数据异常");
        }
        if (StrUtil.isBlank(deviceLock.getLockName())) {
            deviceLock.setLockName("智能锁"+deviceLock.getLockId());
        }
        deviceLock.setUpdateTime(DateUtils.getNowDate());
        int result = deviceLockMapper.updateDeviceLock(deviceLock);
        return result > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    /**
     * 删除设备锁信息
     *
     * @param lockId 设备锁主键
     * @return 结果
     */
    @Override
    @Transactional
    public AjaxResult deleteDeviceLockByLockId(Long lockId, Long longUserId) {
        DeviceLock deviceLock = deviceLockMapper.selectDeviceLockByLockId(lockId);
        if (ObjectUtil.isEmpty(deviceLock)) {
            return AjaxResult.error("设备锁不存在");
        }

        if (longUserId != null) {
            LockFace face = lockFaceService.selectLockFaceByLockIdAndUserId(lockId, longUserId);
            if (ObjectUtil.isEmpty(face)) {
                return AjaxResult.error("当前用户无权限删除该设备锁");
            }
            if (!StrUtil.equals(DeviceLockConstants.AUTH_ROLE_TYPE_MAIN_ADMIN, face.getAuthRoleType())) {
                return AjaxResult.error("非主管理员无权限删除该设备锁");
            }
        }
        lockDevicesService.removeLock(deviceLock.getLockMac());
        lockFaceService.softDeleteLockFaceByLockId(lockId);
        lockPwdService.softDeleteLockPwdByLockId(lockId);
        int result = deviceLockMapper.deleteDeviceLockByLockId(lockId);
        return result > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    @Override
    public TableDataInfo unlockingRecord(Long lockId, Date unlockTime, String userName, Long pwdId, Integer unlockType, Integer pageNum, Integer pageSize) {
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setMsg("查询成功");
        rspData.setRows(null);
        rspData.setTotal(0);

        DeviceLock deviceLock = deviceLockMapper.selectDeviceLockByLockId(lockId);
        if (ObjectUtil.isEmpty(deviceLock)) {
            throw new ServiceException("设备锁不存在");
        }


        StringBuilder params = new StringBuilder();
        params.append("?lockSn=").append(deviceLock.getLockMac());
        String stringTime = DateUtil.formatDate(deviceLock.getCreateTime());
        Date createTime = DateUtil.parse(stringTime, "yyyy-MM-dd");
        Date nowDate = DateUtils.getNowDate();
        if (ObjectUtil.isNotNull(unlockTime)) {
            if (DateUtil.compare(unlockTime, createTime) < 0) {
                unlockTime = createTime;
            }
            params.append("&params%5BbeginUnlockTime%5D=").append(DateUtil.format(unlockTime, "yyyy-MM-dd"));
            params.append("&params%5BendUnlockTime%5D=").append(DateUtil.format(nowDate, "yyyy-MM-dd"));
        } else {
            params.append("&params%5BbeginUnlockTime%5D=").append(DateUtil.format(createTime, "yyyy-MM-dd"));
            params.append("&params%5BendUnlockTime%5D=").append(DateUtil.format(nowDate, "yyyy-MM-dd"));
        }

        if (ObjectUtil.isNotNull(unlockType)) {
            params.append("&unlockType=").append(unlockType);
            if (DeviceLockConstants.LOCK_TYPE_TEMPORARY_PASSWORD.equals(unlockType)) {
                if (pwdId != null) {
                    LockPwd lockPwd = lockPwdService.selectLockPwdByPwdId(pwdId);
                    if (ObjectUtil.isEmpty(lockPwd)) {
                        return rspData;
                    }
                    params.append("&identification=").append(lockPwd.getIdentification());

                }
            }

            if (DeviceLockConstants.LOCK_TYPE_FACE_OPEN.equals(unlockType)) {
                if (StrUtil.isNotEmpty(userName)) {
                    LockFace lockFace = lockFaceService.selectLockFaceByLockIdAndUserName(lockId, userName);
                    if (ObjectUtil.isEmpty(lockFace)) {
                        return rspData;
                    }
                    params.append("&identification=").append(lockFace.getIdentification());

                }
            }
        }

        if (ObjectUtil.isNotNull(pageNum) && ObjectUtil.isNotNull(pageSize)) {
            params.append("&pageNum=").append(pageNum);
            params.append("&pageSize=").append(pageSize);
        }

        JSONObject jsonObject = devicesConfig.sendRequest(RequestMethod.GET, null, "/business/unlockLog/list" + params);

        JSONArray jsonArray = jsonObject.getJSONArray("rows");
        List<Map> maps = JSONArray.parseArray(jsonArray.toJSONString(), Map.class);

        if (maps.size() > 0) {
            List<String> identifications = maps.stream().map(x -> x.get("identification").toString()).distinct().collect(Collectors.toList());
            List<LockFace> lockList = lockFaceService.selectLockListByIdentifications(identifications);
            Map<String, String> names = lockList.stream().collect(Collectors.toMap(LockFace::getIdentification, LockFace::getUserName));
            maps.forEach(x -> {
                String name = names.get(x.get("identification").toString());
                x.put("name", name);
            });
        }
        rspData.setRows(maps);
        rspData.setTotal((Integer) jsonObject.get("total"));
        return rspData;
    }

    @Override
    public void batterySyncTask() {
        List<DeviceLock> deviceLocks = deviceLockMapper.selectDeviceLockTask();
        if (CollectionUtil.isNotEmpty(deviceLocks)) {
            List<String> sns = deviceLocks.stream().map(DeviceLock::getLockMac).collect(Collectors.toList());
            JSONObject jsonObject = lockDevicesService.selectListBySn(sns);
            JSONArray data = jsonObject.getJSONArray("data");
            List<Map> maps = JSONArray.parseArray(data.toJSONString(), Map.class);
            Map<String, Integer> lockMap = new HashMap<>();
            if (!maps.isEmpty()) {
                for (Map map : maps) {
                    lockMap.put(map.get("sn").toString(), Integer.parseInt(map.get("battery").toString()));
                }
                for (DeviceLock deviceLock : deviceLocks) {
                    deviceLock.setBattery(lockMap.get(deviceLock.getLockMac()));
                }
                deviceLockMapper.updateBatchDeviceLock(deviceLocks);
            }
        }
    }

    @Override
    @Transactional
    public AjaxResult manageInsertDeviceLock(DeviceLock deviceLock) {
        if (CollectionUtil.isEmpty(deviceLock.getLockFaceList())) {
            return AjaxResult.error("授权人员为空");
        }
        AjaxResult ajaxResult = this.checkParam(deviceLock);
        if (ajaxResult != null) {
            return ajaxResult;
        }
        Date nowDate = DateUtils.getNowDate();
        deviceLock.setCreateTime(nowDate);
        //设备平台添加锁
        lockDevicesService.createSmartLock(deviceLock);
        int result = deviceLockMapper.insertDeviceLock(deviceLock);

        if (result > 0) {
            StringBuilder errMsg = new StringBuilder("授权失败的用户：");
            List<LockFace> lockFaceList = new ArrayList<>();
            List<LockOperatingRecord> lockOperatingRecordList = new ArrayList<>();
            LocalDate nowLocalDate = LocalDate.now();
            List<String> phoneList = deviceLock.getLockFaceList().stream().map(LockFace::getUserPhone).filter(StrUtil::isNotBlank).collect(Collectors.toList());
            Map<String, User> userMap = null;
            Map<Long, Group> groupMap = null;
            if (!phoneList.isEmpty()) {
                List<User> users = userService.selectUserByPhoneList(phoneList);
                if (CollectionUtil.isNotEmpty(users)) {
                    userMap = users.stream().collect(Collectors.toMap(User::getPhone, x -> x));
                    List<Long> userIds = users.stream().map(User::getUserId).collect(Collectors.toList());
                    List<Group> groups = groupService.selectGroupByGroupIds(userIds);
                    groupMap = groups.stream().collect(Collectors.toMap(Group::getUserId, x -> x));
                }
            }
            for (LockFace lockFace : deviceLock.getLockFaceList()) {
                try {
                    if (StrUtil.equals(DeviceLockConstants.AUTH_TIME_TYPE_LONG, lockFace.getAuthTimeType())) {
                        Date date = DateUtils.addYears(lockFace.getAuthStartTime(), 20);
                        lockFace.setAuthEndTime(date);
                    }
                    lockFace.setLockId(deviceLock.getLockId());
                    ajaxResult = lockFaceService.checkParam(lockFace);
                    if (ajaxResult != null) {
                        errMsg.append(lockFace.getUserName()).append("，");
                        continue;
                    }
                    LocalDate startTime = lockFace.getAuthStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                    if (nowLocalDate.isAfter(startTime)) {
                        errMsg.append(lockFace.getUserName()).append("，");
                        continue;
                    }
                    if (StrUtil.isNotBlank(lockFace.getUserPhone())) {
                        User user = null;
                        if (userMap != null) {
                            user = userMap.get(lockFace.getUserPhone());
                        }
                        Group group;
                        if (ObjectUtil.isEmpty(user)) {
                            user = new User();
                            user.setPhone(lockFace.getUserPhone());
                            user.setNickName("未命名");
                            user.setUserName(lockFace.getUserName());
                            user.setCreateTime(nowDate);
                            userService.insertUser(user);

                            group = new Group();
                            group.setGroupName("默认");
                            group.setUserId(user.getUserId());
                            group.setGroupType(DeviceLockConstants.GROUP_TYPE_NON_DEFAULT);
                            group.setCreateBy(lockFace.getUserName());
                            groupService.insertGroup(group);
                        } else {
                            group = groupMap.get(user.getUserId());
                        }
                        lockFace.setUserId(user.getUserId());
                        lockFace.setGroupId(group.getGroupId());
                    }
                    String identification = lockDevicesService.getIdentification();
                    lockFace.setIdentification(identification);
                    lockFace.setCreateTime(nowDate);
                    lockFace.setCreateBy(deviceLock.getCreateBy());
                    if (StrUtil.isNotBlank(lockFace.getFaceImage())) {
                        lockDevicesService.createLockFace(lockFace.getFaceImage(), deviceLock.getLockMac(), identification, lockFace.getAuthStartTime(), lockFace.getAuthEndTime());
                    }
                    lockFaceList.add(lockFace);

                    // 锁操作记录
                    LockOperatingRecord lockOperatingRecord = new LockOperatingRecord();
                    lockOperatingRecord.setLockId(deviceLock.getLockId());
                    lockOperatingRecord.setOperatingType(DeviceLockConstants.OPERATING_TYPE_DELETE);
                    lockOperatingRecord.setOperatingContent("新增授权人脸：" + deviceLock.getLockId());
                    lockOperatingRecord.setCreateBy(lockFace.getUserName());
                    lockOperatingRecord.setCreateTime(nowDate);
                    lockOperatingRecordList.add(lockOperatingRecord);
                } catch (Exception e) {
                    errMsg.append(lockFace.getUserName()).append("，");
                }
            }

            if (!lockFaceList.isEmpty()) {
                lockFaceService.insertBatchLockFace(lockFaceList);
            }
            if (!lockOperatingRecordList.isEmpty()) {
                lockOperatingRecordService.batchInsertLockOperatingRecord(lockOperatingRecordList);
            }

            return StrUtil.equals(errMsg.toString(), "授权失败的用户：") ? AjaxResult.success() : AjaxResult.error(errMsg + "请重新授权");
        }
        return AjaxResult.success();
    }

    @Override
    public int countDeviceLockByModelId(Long modelId) {
        return deviceLockMapper.countDeviceLockByModelId(modelId);
    }

    @Override
    public void onlineStatusSyncTask() {
        try {
            // 查询需要同步状态的设备
            List<DeviceLock> deviceLocks = deviceLockMapper.selectDeviceLockTask();
            if (CollectionUtil.isEmpty(deviceLocks)) {
                return; // 没有设备需要处理
            }

            // 获取所有设备的最新状态
            Map<String, String> deviceStatusMap = fetchAllDeviceStatus();

            // 更新设备在线状态
            updateDeviceOnlineStatus(deviceLocks, deviceStatusMap);

            // 批量更新设备状态到数据库
            if (!deviceLocks.isEmpty()) {
                deviceLockMapper.updateBatchDeviceLock(deviceLocks);
            }
        } catch (Exception e) {
            log.error("更新智能锁在线状态失败", e);
        }
    }

    @Override
    public Map<String, Map<String, Object>> homePageCountOnlineStatus() {
        return deviceLockMapper.homePageCountOnlineStatus();
    }

    private Map<String, String> fetchAllDeviceStatus() {
        Map<String, String> deviceStatusMap = new HashMap<>();
        final int PAGE_SIZE = 500;
        int pageNum = 1;
        boolean hasMoreData = true;

        while (hasMoreData) {
            // 构建分页查询参数
            Map<String, Object> pageParam = new HashMap<>();
            pageParam.put("pageNum", pageNum);
            pageParam.put("pageSize", PAGE_SIZE);

            // 调用服务获取数据
            JSONObject response = lockDevicesService.selectListAll(pageParam);
            Object smartLockData = response.get("data");
            smartLockData = JSONObject.parseObject(smartLockData.toString()).get("smartLockHXK");
            String total = JSONObject.parseObject(smartLockData.toString()).get("total").toString();
            int totalInt = Integer.parseInt(total);

            if (smartLockData == null) {
                break; // 没有数据，退出循环
            }

            // 处理当前页的设备状态
            Object result = JSONObject.parseObject(smartLockData.toString()).get("result");
            List<Map> maps = JSONArray.parseArray(result.toString(), Map.class);
            for (Map map1 : maps) {
                String deviceMac = map1.get("deviceMac").toString();
                String modifyTime = map1.get("modifyTime").toString();
                if (deviceMac != null && modifyTime != null) {
                    deviceStatusMap.put(deviceMac, modifyTime);
                }
            }

            // 判断是否还有下一页数据
            hasMoreData = (pageNum * PAGE_SIZE) < totalInt;
            pageNum++;
        }

        return deviceStatusMap;
    }

    private void updateDeviceOnlineStatus(List<DeviceLock> deviceLocks, Map<String, String> deviceStatusMap) {
        LocalDateTime now = LocalDateTime.now();
        for (DeviceLock deviceLock : deviceLocks) {
            String modifyTime = deviceStatusMap.get(deviceLock.getLockMac());

            if (StrUtil.isNotEmpty(modifyTime)) {
                try {
                    // 解析最后修改时间并计算与当前时间的差值
                    LocalDateTime lastUpdateTime = LocalDateTime.parse(modifyTime, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
                    long hoursDiff = ChronoUnit.HOURS.between(lastUpdateTime, now);

                    // 根据时间差设置在线状态
                    deviceLock.setOnlineStatus(
                            hoursDiff > 4 ?
                                    DeviceLockConstants.ONLINE_STATUS_OFFLINE :
                                    DeviceLockConstants.ONLINE_STATUS_ONLINE
                    );
                } catch (DateTimeParseException e) {
                    log.warn("设备的modifyTime格式无效：{}", deviceLock.getLockMac(), e);
                }
            }
        }
    }

    public AjaxResult checkParam(DeviceLock deviceLock) {
        /*if (StrUtil.isBlank(deviceLock.getLockName()) || deviceLock.getLockName().length() > 15) {
            return AjaxResult.error("设备锁名称格式有误,请重新输入");
        }*/
        if (StrUtil.isBlank(deviceLock.getLockMac())) {
            return AjaxResult.error("设备锁MAC地址不能为空");
        }
        List<Map<String, Object>> maps = deviceLockMapper.checkNameAneMac(deviceLock);
        if (CollectionUtil.isNotEmpty(maps)) {
            for (Map<String, Object> map : maps) {
                if (Integer.parseInt(map.get("num").toString()) > 0) {
                    String type = map.get("type").toString();
                    switch (type) {
                        case "1":
                            return AjaxResult.error("设备锁名称已存在,请重新输入");
                        case "2":
                            return AjaxResult.error("该锁已被绑定,请检查mac是否正确");
                    }
                }
            }
        }
        return null;
    }
}
